﻿package config {

import com.whirled.AvatarControl;
import com.whirled.ControlEvent;
import com.whirled.contrib.ColorMatrix;

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.filters.BitmapFilter;
import flash.filters.ColorMatrixFilter;

public class BocreaBody extends MovieClipBody
{
    public function BocreaBody (ctrl :AvatarControl, media :MovieClip, width :int, height :int = -1)
    {
        super(ctrl, media, width, height);

        // We are configurable only by the player that owns us
        if (_ctrl.hasControl()) {
            _ctrl.registerCustomConfig(createConfigPanel);
        }

        // Load our current config right now, and respond to MEMORY_CHANGED events by
        // reloading it.
        loadConfig();
        _ctrl.addEventListener(ControlEvent.MEMORY_CHANGED,
            function (e :ControlEvent) :void {
                if (e.name == MEMORY_CONFIG) {
                    loadConfig();
                }
            });
    }

    protected function createConfigPanel () :Sprite
    {
        return new BocreaPanel(
            _curBocreaData,
            function (newConfig :BocreaData) :void {
                saveConfig(newConfig);
                applyConfig(newConfig);
            });
    }

    protected function loadConfig () :void
    {
        var configData :BocreaData = new BocreaData();
        configData.fromMemory(_ctrl.getMemory(MEMORY_CONFIG));
        applyConfig(configData);
    }

    protected function saveConfig (configData :BocreaData) :void
    {
        _ctrl.setMemory(MEMORY_CONFIG, configData.toMemory(),
            function (success :Boolean) :void {
                if (!success) {
                    log.warning("Failed to save Config!");
                }
            });
    }

    protected function applyConfig (config :BocreaData) :void
    {
        _curBocreaData = config;
        var allMovies :Array = getAllMovies();
        selectCurConfigFrames(allMovies);
        applyCurConfigFilters(allMovies);
    }

    protected function selectCurConfigFrames (movies :Array) :void
    {
        //log.info("Selecting frames for " + movies.length + " movies");

        for each (var movie :MovieClip in movies) {
            // Shirt
			
            selectFrame(movie, [ "state", "head", "hat" ], _curBocreaData.hatNumber);
            selectFrame(movie, [ "state", "head", "hat" ], _curBocreaData.hatNumber);
            selectFrame(movie, [ "state", "head", "hat" ], _curBocreaData.hatNumber);
            selectFrame(movie, [ "state", "head", "hat" ], _curBocreaData.hatNumber);
			selectFrame(movie, [ "state", "head", "hat" ], _curBocreaData.hatNumber);
			selectFrame(movie, [ "state", "head", "hat" ], _curBocreaData.hatNumber);
			selectFrame(movie, [ "state", "head", "hat" ], _curBocreaData.hatNumber);

			/**
			selectFrame(movie, [ "head", "beard" ], _curBocreaData.beardNumber);
            selectFrame(movie, [ "head", "beard" ], _curBocreaData.beardNumber);
            selectFrame(movie, [ "head", "beard" ], _curBocreaData.beardNumber);
			*/
        }
    }

    protected function applyCurConfigFilters (movies :Array) :void
    {
        //log.info("Applying filters to " + movies.length + " movies");

        var rlegFilter :ColorMatrixFilter = createColorFilter(_curBocreaData.rlegColor);
        var llegFilter :ColorMatrixFilter = createColorFilter(_curBocreaData.llegColor);
        var learFilter :ColorMatrixFilter = createColorFilter(_curBocreaData.learColor);
		var rearFilter :ColorMatrixFilter = createColorFilter(_curBocreaData.rearColor);
		var bodyFilter :ColorMatrixFilter = createColorFilter(_curBocreaData.bodyColor);
		var larmFilter :ColorMatrixFilter = createColorFilter(_curBocreaData.larmColor);
		var rarmFilter :ColorMatrixFilter = createColorFilter(_curBocreaData.rarmColor);
		var mouthFilter :ColorMatrixFilter = createColorFilter(_curBocreaData.mouthColor);
		var headFilter :ColorMatrixFilter = createColorFilter(_curBocreaData.headColor);
		var hatFilter :ColorMatrixFilter = createColorFilter(_curBocreaData.hatColor);
		
        for each (var movie :MovieClip in movies) {
            // Fur colors
            applyFilter(movie, [ "state", "rleg", "rlegs" ], rlegFilter);
            applyFilter(movie, [ "state", "lleg", "llegs" ], llegFilter);
            applyFilter(movie, [ "state", "lear", "lears" ], learFilter);
            applyFilter(movie, [ "state", "rear", "rears" ], rearFilter);
            applyFilter(movie, [ "state", "body", "bodys" ], bodyFilter);
            applyFilter(movie, [ "state", "larm", "larms" ], larmFilter);
			applyFilter(movie, [ "state", "rarm", "rarms" ], rarmFilter);
			applyFilter(movie, [ "state", "mouth", "mouths" ], mouthFilter);
            applyFilter(movie, [ "state", "head", "heads" ], headFilter);
			applyFilter(movie, [ "state", "head", "hat" ], hatFilter);

            // Beard color
//            applyFilter(movie, [ "head", "beard" ], beardFilter);
//            applyFilter(movie, [ "head", "beard" ], beardFilter);
//            applyFilter(movie, [ "head", "beard" ], beardFilter);

            // Hair color
//            applyFilter(movie, [ "head", "brow" ], hairFilter);
 //           applyFilter(movie, [ "head", "hair" ], hairFilter);
  //          applyFilter(movie, [ "head", "hair" ], hairFilter);
 //           applyFilter(movie, [ "head", "hair" ], hairFilter);
 //           applyFilter(movie, [ "head", "hair" ], hairFilter);
        }
    }

    override protected function playMovie (movie :MovieClip) :void
    {
        super.playMovie(movie);

        if (movie != null) {
            //log.info("Restarting movies");
            // recursively restart all movies
            restartAllMovies(movie);
            // and reselect our configurations
            selectCurConfigFrames([ movie ]);
        }
    }

    protected static function restartAllMovies (disp :DisplayObjectContainer) :void
    {
        if (disp is MovieClip) {
            (disp as MovieClip).gotoAndPlay(1);
        }

        for (var ii :int = 0; ii < disp.numChildren; ++ii) {
            var child :DisplayObject = disp.getChildAt(ii);
            if (child is DisplayObjectContainer) {
                restartAllMovies(child as DisplayObjectContainer);
            }
        }
    }

    protected static function findChild (movie :MovieClip, childPath :Array) :MovieClip
    {
        var child :MovieClip = movie;
        for each (var pathElt :String in childPath) {
            child = child[pathElt];
            if (child == null) {
                break;
            }
        }

        return child;
    }

    protected static function selectFrame (movie :MovieClip, childPath :Array,
                                           frameNumber :int) :void
    {
        var child :MovieClip = findChild(movie, childPath);
        if (child != null) {
            child.gotoAndStop(frameNumber);
        }
    }

    protected static function applyFilter (movie :MovieClip, childPath :Array,
                                           filter :BitmapFilter) :void
    {
        var child :MovieClip = findChild(movie, childPath);
        if (child != null) {
            child.filters = [ filter ];
        }
    }

    protected static function createColorFilter (color :uint) :ColorMatrixFilter
    {
        return new ColorMatrix().colorize(color).createFilter();
    }

    protected var _curBocreaData :BocreaData;

    protected static const MEMORY_CONFIG :String = "Config";
}

}
